package com.swak.timer;

/**
 * 统计 RTO 对象: 不是线程安全
 * 
 * @author 618lf
 */
public class RTO {

	/**
	 * 加权系数
	 */
	private Double a = 0.125d;

	/**
	 * 加权系数
	 */
	private Double b = 0.25d;

	/**
	 * 基于移动平均统计的RTT
	 */
	private Long estimateRTT;

	/**
	 * 基于移动平均统计的 标准差
	 */
	private Long devRTT;

	/**
	 * 当前计算的 RTO 值
	 */
	private Long timeoutInerval;

	/**
	 * 传入当前监测的： RTT
	 * 
	 * @param rtt
	 */
	public RTO calculate(long sampleRTT) {

		/*
		 * 第一次监测
		 */
		if (estimateRTT == null) {
			estimateRTT = sampleRTT;
			devRTT = sampleRTT / 2;
		}

		/*
		 * 后期监测
		 */
		else {

			/*
			 * 计算 estimateRTT
			 */
			estimateRTT = (long) ((1 - a) * estimateRTT + a * sampleRTT);

			/*
			 * 第 一、二、 三、四 次 ; a = 0.125,越是之前的数据所起的作用越小（指数级下降）
			 */
			// sampleRTT1
			// (1 - a) * sampleRTT1 + a * sampleRTT2
			// (1 - a) * 【 (1 - a) * sampleRTT1 + a * sampleRTT2 】 + a * sampleRTT3
			// (1 - a) * 【 (1 - a) * 【 (1 - a) * sampleRTT1 + a * sampleRTT2 】 + a *
			// sampleRTT3 】 + a * sampleRTT4
			// sampleRTT1: (1 - a) * (1 - a) * (1 - a)
			// sampleRTT2: (1 - a) * (1 - a) * a
			// sampleRTT3: (1 - a) * a
			// sampleRTT3: a

			/*
			 * 计算 devRTT ; b = 0.25
			 * 分析同上
			 */
			devRTT = (long) ((1 - b) * devRTT + b * Math.abs(estimateRTT - sampleRTT));
		}

		/*
		 * 当前的 RTO
		 */
		this.timeoutInerval = estimateRTT + 4 * devRTT;

		/*
		 * 返回当前的对象
		 */
		return this;
	}

	/**
	 * 返回计算的 RTO 值 
	 * 
	 * @return
	 */
	public long getTimeoutInerval() {
		return timeoutInerval;
	}
}
